package com.lifeverse.service;

import com.lifeverse.entity.LifeEntity;
import com.lifeverse.entity.LifeEntityRelationship;
import com.lifeverse.repository.LifeEntityRelationshipRepository;
import com.lifeverse.repository.LifeEntityRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 网络拓扑服务
 * 管理生命体网络的拓扑结构
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NetworkTopologyService {
    
    private final LifeEntityRepository lifeEntityRepository;
    private final LifeEntityRelationshipRepository relationshipRepository;
    
    /**
     * 网络拓扑数据结构
     */
    public static class NetworkTopology {
        private Map<Long, NetworkNode> nodes;
        private Map<String, NetworkEdge> edges;
        private NetworkMetrics metrics;
        
        public NetworkTopology() {
            this.nodes = new HashMap<>();
            this.edges = new HashMap<>();
            this.metrics = new NetworkMetrics();
        }
        
        // Getters and Setters
        public Map<Long, NetworkNode> getNodes() { return nodes; }
        public void setNodes(Map<Long, NetworkNode> nodes) { this.nodes = nodes; }
        
        public Map<String, NetworkEdge> getEdges() { return edges; }
        public void setEdges(Map<String, NetworkEdge> edges) { this.edges = edges; }
        
        public NetworkMetrics getMetrics() { return metrics; }
        public void setMetrics(NetworkMetrics metrics) { this.metrics = metrics; }
    }
    
    /**
     * 网络节点
     */
    public static class NetworkNode {
        private Long id;
        private String name;
        private String type;
        private String status;
        private Integer degree;
        private BigDecimal centrality;
        private Set<Long> neighbors;
        private Map<String, Object> attributes;
        
        public NetworkNode() {
            this.neighbors = new HashSet<>();
            this.attributes = new HashMap<>();
        }
        
        // Getters and Setters
        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }
        
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getStatus() { return status; }
        public void setStatus(String status) { this.status = status; }
        
        public Integer getDegree() { return degree; }
        public void setDegree(Integer degree) { this.degree = degree; }
        
        public BigDecimal getCentrality() { return centrality; }
        public void setCentrality(BigDecimal centrality) { this.centrality = centrality; }
        
        public Set<Long> getNeighbors() { return neighbors; }
        public void setNeighbors(Set<Long> neighbors) { this.neighbors = neighbors; }
        
        public Map<String, Object> getAttributes() { return attributes; }
        public void setAttributes(Map<String, Object> attributes) { this.attributes = attributes; }
    }
    
    /**
     * 网络边
     */
    public static class NetworkEdge {
        private String id;
        private Long sourceId;
        private Long targetId;
        private String relationshipType;
        private BigDecimal weight;
        private BigDecimal strength;
        private Boolean directed;
        private Map<String, Object> attributes;
        
        public NetworkEdge() {
            this.attributes = new HashMap<>();
        }
        
        // Getters and Setters
        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        
        public Long getSourceId() { return sourceId; }
        public void setSourceId(Long sourceId) { this.sourceId = sourceId; }
        
        public Long getTargetId() { return targetId; }
        public void setTargetId(Long targetId) { this.targetId = targetId; }
        
        public String getRelationshipType() { return relationshipType; }
        public void setRelationshipType(String relationshipType) { this.relationshipType = relationshipType; }
        
        public BigDecimal getWeight() { return weight; }
        public void setWeight(BigDecimal weight) { this.weight = weight; }
        
        public BigDecimal getStrength() { return strength; }
        public void setStrength(BigDecimal strength) { this.strength = strength; }
        
        public Boolean getDirected() { return directed; }
        public void setDirected(Boolean directed) { this.directed = directed; }
        
        public Map<String, Object> getAttributes() { return attributes; }
        public void setAttributes(Map<String, Object> attributes) { this.attributes = attributes; }
    }
    
    /**
     * 网络指标
     */
    public static class NetworkMetrics {
        private Integer nodeCount;
        private Integer edgeCount;
        private BigDecimal density;
        private BigDecimal averageDegree;
        private BigDecimal clusteringCoefficient;
        private Integer diameter;
        private BigDecimal averagePathLength;
        private Integer connectedComponents;
        private Map<String, Object> additionalMetrics;
        
        public NetworkMetrics() {
            this.additionalMetrics = new HashMap<>();
        }
        
        // Getters and Setters
        public Integer getNodeCount() { return nodeCount; }
        public void setNodeCount(Integer nodeCount) { this.nodeCount = nodeCount; }
        
        public Integer getEdgeCount() { return edgeCount; }
        public void setEdgeCount(Integer edgeCount) { this.edgeCount = edgeCount; }
        
        public BigDecimal getDensity() { return density; }
        public void setDensity(BigDecimal density) { this.density = density; }
        
        public BigDecimal getAverageDegree() { return averageDegree; }
        public void setAverageDegree(BigDecimal averageDegree) { this.averageDegree = averageDegree; }
        
        public BigDecimal getClusteringCoefficient() { return clusteringCoefficient; }
        public void setClusteringCoefficient(BigDecimal clusteringCoefficient) { this.clusteringCoefficient = clusteringCoefficient; }
        
        public Integer getDiameter() { return diameter; }
        public void setDiameter(Integer diameter) { this.diameter = diameter; }
        
        public BigDecimal getAveragePathLength() { return averagePathLength; }
        public void setAveragePathLength(BigDecimal averagePathLength) { this.averagePathLength = averagePathLength; }
        
        public Integer getConnectedComponents() { return connectedComponents; }
        public void setConnectedComponents(Integer connectedComponents) { this.connectedComponents = connectedComponents; }
        
        public Map<String, Object> getAdditionalMetrics() { return additionalMetrics; }
        public void setAdditionalMetrics(Map<String, Object> additionalMetrics) { this.additionalMetrics = additionalMetrics; }
    }
    
    /**
     * 构建全局网络拓扑
     */
    public NetworkTopology buildGlobalNetworkTopology() {
        log.info("构建全局网络拓扑");
        
        List<LifeEntity> allEntities = lifeEntityRepository.findAll();
        List<LifeEntityRelationship> allRelationships = relationshipRepository.findActiveRelationships();
        
        return buildNetworkTopology(allEntities, allRelationships);
    }
    
    /**
     * 构建指定生命体的局部网络拓扑
     */
    public NetworkTopology buildLocalNetworkTopology(Long entityId, int depth) {
        log.info("构建局部网络拓扑: entityId={}, depth={}", entityId, depth);
        
        LifeEntity centerEntity = lifeEntityRepository.findById(entityId)
                .orElseThrow(() -> new RuntimeException("生命体不存在: " + entityId));
        
        Set<LifeEntity> entities = new HashSet<>();
        Set<LifeEntityRelationship> relationships = new HashSet<>();
        
        // 递归收集指定深度的网络
        collectLocalNetwork(centerEntity, depth, entities, relationships, new HashSet<>());
        
        return buildNetworkTopology(new ArrayList<>(entities), new ArrayList<>(relationships));
    }
    
    /**
     * 构建网络拓扑
     */
    private NetworkTopology buildNetworkTopology(List<LifeEntity> entities, List<LifeEntityRelationship> relationships) {
        NetworkTopology topology = new NetworkTopology();
        
        // 构建节点
        for (LifeEntity entity : entities) {
            NetworkNode node = createNetworkNode(entity);
            topology.getNodes().put(entity.getId(), node);
        }
        
        // 构建边
        for (LifeEntityRelationship relationship : relationships) {
            NetworkEdge edge = createNetworkEdge(relationship);
            topology.getEdges().put(edge.getId(), edge);
            
            // 更新节点的邻居信息
            NetworkNode sourceNode = topology.getNodes().get(relationship.getSourceEntity().getId());
            NetworkNode targetNode = topology.getNodes().get(relationship.getTargetEntity().getId());
            
            if (sourceNode != null && targetNode != null) {
                sourceNode.getNeighbors().add(targetNode.getId());
                if (!relationship.getIsBidirectional()) {
                    targetNode.getNeighbors().add(sourceNode.getId());
                }
            }
        }
        
        // 计算节点度数
        calculateNodeDegrees(topology);
        
        // 计算网络指标
        calculateNetworkMetrics(topology);
        
        // 计算中心性
        calculateCentrality(topology);
        
        return topology;
    }
    
    /**
     * 创建网络节点
     */
    private NetworkNode createNetworkNode(LifeEntity entity) {
        NetworkNode node = new NetworkNode();
        node.setId(entity.getId());
        node.setName(entity.getName());
        node.setType(entity.getType().name());
        node.setStatus(entity.getStatus().name());
        
        // 添加额外属性
        node.getAttributes().put("description", entity.getDescription());
        node.getAttributes().put("createdAt", entity.getCreatedAt());
        node.getAttributes().put("updatedAt", entity.getUpdatedAt());
        
        return node;
    }
    
    /**
     * 创建网络边
     */
    private NetworkEdge createNetworkEdge(LifeEntityRelationship relationship) {
        NetworkEdge edge = new NetworkEdge();
        edge.setId(relationship.getSourceEntity().getId() + "-" + relationship.getTargetEntity().getId());
        edge.setSourceId(relationship.getSourceEntity().getId());
        edge.setTargetId(relationship.getTargetEntity().getId());
        edge.setRelationshipType(relationship.getRelationshipType().name());
        edge.setWeight(relationship.getNetworkWeight());
        edge.setStrength(relationship.getRelationshipStrength());
        edge.setDirected(!relationship.getIsBidirectional());
        
        // 添加额外属性
        edge.getAttributes().put("quality", relationship.getRelationshipQuality());
        edge.getAttributes().put("trustLevel", relationship.getTrustLevel());
        edge.getAttributes().put("interactionFrequency", relationship.getInteractionFrequency());
        edge.getAttributes().put("establishedAt", relationship.getEstablishedAt());
        edge.getAttributes().put("lastInteractionAt", relationship.getLastInteractionAt());
        
        return edge;
    }
    
    /**
     * 递归收集局部网络
     */
    private void collectLocalNetwork(LifeEntity entity, int remainingDepth, 
                                   Set<LifeEntity> entities, Set<LifeEntityRelationship> relationships,
                                   Set<Long> visited) {
        if (remainingDepth <= 0 || visited.contains(entity.getId())) {
            return;
        }
        
        visited.add(entity.getId());
        entities.add(entity);
        
        // 获取该生命体的所有活跃关系
        List<LifeEntityRelationship> entityRelationships = relationshipRepository.findActiveRelationshipsByEntity(entity);
        
        for (LifeEntityRelationship relationship : entityRelationships) {
            relationships.add(relationship);
            
            // 递归处理相关的生命体
            LifeEntity relatedEntity = relationship.getSourceEntity().equals(entity) 
                    ? relationship.getTargetEntity() 
                    : relationship.getSourceEntity();
            
            collectLocalNetwork(relatedEntity, remainingDepth - 1, entities, relationships, visited);
        }
    }
    
    /**
     * 计算节点度数
     */
    private void calculateNodeDegrees(NetworkTopology topology) {
        for (NetworkNode node : topology.getNodes().values()) {
            node.setDegree(node.getNeighbors().size());
        }
    }
    
    /**
     * 计算网络指标
     */
    private void calculateNetworkMetrics(NetworkTopology topology) {
        NetworkMetrics metrics = topology.getMetrics();
        
        int nodeCount = topology.getNodes().size();
        int edgeCount = topology.getEdges().size();
        
        metrics.setNodeCount(nodeCount);
        metrics.setEdgeCount(edgeCount);
        
        if (nodeCount > 1) {
            // 计算网络密度
            double maxPossibleEdges = nodeCount * (nodeCount - 1) / 2.0;
            double density = edgeCount / maxPossibleEdges;
            metrics.setDensity(BigDecimal.valueOf(density));
            
            // 计算平均度数
            double averageDegree = (2.0 * edgeCount) / nodeCount;
            metrics.setAverageDegree(BigDecimal.valueOf(averageDegree));
        } else {
            metrics.setDensity(BigDecimal.ZERO);
            metrics.setAverageDegree(BigDecimal.ZERO);
        }
        
        // 计算聚类系数（简化实现）
        metrics.setClusteringCoefficient(calculateClusteringCoefficient(topology));
        
        // 计算连通分量数
        metrics.setConnectedComponents(calculateConnectedComponents(topology));
        
        // 计算网络直径和平均路径长度（简化实现）
        PathMetrics pathMetrics = calculatePathMetrics(topology);
        metrics.setDiameter(pathMetrics.diameter);
        metrics.setAveragePathLength(pathMetrics.averagePathLength);
    }
    
    /**
     * 计算聚类系数
     */
    private BigDecimal calculateClusteringCoefficient(NetworkTopology topology) {
        double totalClusteringCoefficient = 0;
        int nodeCount = 0;
        
        for (NetworkNode node : topology.getNodes().values()) {
            if (node.getDegree() < 2) {
                continue; // 度数小于2的节点聚类系数为0
            }
            
            Set<Long> neighbors = node.getNeighbors();
            int possibleEdges = neighbors.size() * (neighbors.size() - 1) / 2;
            int actualEdges = 0;
            
            // 计算邻居之间的实际连接数
            for (Long neighbor1 : neighbors) {
                for (Long neighbor2 : neighbors) {
                    if (!neighbor1.equals(neighbor2)) {
                        String edgeId1 = neighbor1 + "-" + neighbor2;
                        String edgeId2 = neighbor2 + "-" + neighbor1;
                        if (topology.getEdges().containsKey(edgeId1) || topology.getEdges().containsKey(edgeId2)) {
                            actualEdges++;
                        }
                    }
                }
            }
            actualEdges /= 2; // 避免重复计算
            
            double clusteringCoefficient = possibleEdges > 0 ? (double) actualEdges / possibleEdges : 0;
            totalClusteringCoefficient += clusteringCoefficient;
            nodeCount++;
        }
        
        return nodeCount > 0 ? BigDecimal.valueOf(totalClusteringCoefficient / nodeCount) : BigDecimal.ZERO;
    }
    
    /**
     * 计算连通分量数
     */
    private Integer calculateConnectedComponents(NetworkTopology topology) {
        Set<Long> visited = new HashSet<>();
        int components = 0;
        
        for (Long nodeId : topology.getNodes().keySet()) {
            if (!visited.contains(nodeId)) {
                dfsVisit(nodeId, topology, visited);
                components++;
            }
        }
        
        return components;
    }
    
    /**
     * 深度优先搜索访问
     */
    private void dfsVisit(Long nodeId, NetworkTopology topology, Set<Long> visited) {
        visited.add(nodeId);
        NetworkNode node = topology.getNodes().get(nodeId);
        
        if (node != null) {
            for (Long neighborId : node.getNeighbors()) {
                if (!visited.contains(neighborId)) {
                    dfsVisit(neighborId, topology, visited);
                }
            }
        }
    }
    
    /**
     * 路径指标
     */
    private static class PathMetrics {
        int diameter = 0;
        BigDecimal averagePathLength = BigDecimal.ZERO;
    }
    
    /**
     * 计算路径指标（简化实现）
     */
    private PathMetrics calculatePathMetrics(NetworkTopology topology) {
        PathMetrics metrics = new PathMetrics();
        
        // 简化实现：基于网络大小估算
        int nodeCount = topology.getNodes().size();
        if (nodeCount > 1) {
            metrics.diameter = (int) Math.ceil(Math.log(nodeCount) / Math.log(2)) + 1;
            metrics.averagePathLength = BigDecimal.valueOf(Math.log(nodeCount) / Math.log(2));
        }
        
        return metrics;
    }
    
    /**
     * 计算中心性
     */
    private void calculateCentrality(NetworkTopology topology) {
        // 简化的度中心性计算
        int maxDegree = topology.getNodes().values().stream()
                .mapToInt(NetworkNode::getDegree)
                .max()
                .orElse(1);
        
        for (NetworkNode node : topology.getNodes().values()) {
            double centrality = maxDegree > 0 ? (double) node.getDegree() / maxDegree : 0;
            node.setCentrality(BigDecimal.valueOf(centrality));
        }
    }
    
    /**
     * 查找最短路径
     */
    public List<Long> findShortestPath(NetworkTopology topology, Long sourceId, Long targetId) {
        if (!topology.getNodes().containsKey(sourceId) || !topology.getNodes().containsKey(targetId)) {
            return Collections.emptyList();
        }
        
        Map<Long, Long> parent = new HashMap<>();
        Set<Long> visited = new HashSet<>();
        Queue<Long> queue = new LinkedList<>();
        
        queue.offer(sourceId);
        visited.add(sourceId);
        parent.put(sourceId, null);
        
        while (!queue.isEmpty()) {
            Long current = queue.poll();
            
            if (current.equals(targetId)) {
                // 重构路径
                List<Long> path = new ArrayList<>();
                Long node = targetId;
                while (node != null) {
                    path.add(0, node);
                    node = parent.get(node);
                }
                return path;
            }
            
            NetworkNode currentNode = topology.getNodes().get(current);
            if (currentNode != null) {
                for (Long neighborId : currentNode.getNeighbors()) {
                    if (!visited.contains(neighborId)) {
                        visited.add(neighborId);
                        parent.put(neighborId, current);
                        queue.offer(neighborId);
                    }
                }
            }
        }
        
        return Collections.emptyList(); // 没有找到路径
    }
    
    /**
     * 查找节点的k跳邻居
     */
    public Set<Long> findKHopNeighbors(NetworkTopology topology, Long nodeId, int k) {
        Set<Long> neighbors = new HashSet<>();
        Set<Long> currentLevel = new HashSet<>();
        Set<Long> visited = new HashSet<>();
        
        currentLevel.add(nodeId);
        visited.add(nodeId);
        
        for (int hop = 0; hop < k; hop++) {
            Set<Long> nextLevel = new HashSet<>();
            
            for (Long current : currentLevel) {
                NetworkNode node = topology.getNodes().get(current);
                if (node != null) {
                    for (Long neighborId : node.getNeighbors()) {
                        if (!visited.contains(neighborId)) {
                            nextLevel.add(neighborId);
                            visited.add(neighborId);
                            if (hop > 0) { // 不包括自己
                                neighbors.add(neighborId);
                            }
                        }
                    }
                }
            }
            
            currentLevel = nextLevel;
        }
        
        return neighbors;
    }
    
    /**
     * 获取网络拓扑摘要
     */
    public Map<String, Object> getTopologySummary(NetworkTopology topology) {
        Map<String, Object> summary = new HashMap<>();
        
        NetworkMetrics metrics = topology.getMetrics();
        summary.put("nodeCount", metrics.getNodeCount());
        summary.put("edgeCount", metrics.getEdgeCount());
        summary.put("density", metrics.getDensity());
        summary.put("averageDegree", metrics.getAverageDegree());
        summary.put("clusteringCoefficient", metrics.getClusteringCoefficient());
        summary.put("connectedComponents", metrics.getConnectedComponents());
        summary.put("diameter", metrics.getDiameter());
        summary.put("averagePathLength", metrics.getAveragePathLength());
        
        // 节点类型分布
        Map<String, Long> nodeTypeDistribution = topology.getNodes().values().stream()
                .collect(Collectors.groupingBy(NetworkNode::getType, Collectors.counting()));
        summary.put("nodeTypeDistribution", nodeTypeDistribution);
        
        // 边类型分布
        Map<String, Long> edgeTypeDistribution = topology.getEdges().values().stream()
                .collect(Collectors.groupingBy(NetworkEdge::getRelationshipType, Collectors.counting()));
        summary.put("edgeTypeDistribution", edgeTypeDistribution);
        
        // 度数分布
        Map<Integer, Long> degreeDistribution = topology.getNodes().values().stream()
                .collect(Collectors.groupingBy(NetworkNode::getDegree, Collectors.counting()));
        summary.put("degreeDistribution", degreeDistribution);
        
        return summary;
    }
}